package com.itHsuSE.experiment;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * Experiment7_2：文件与数据流扩展
 * 在实验5的基础上，增加“保存文件”和“读取文件”按钮，实现List中对象保存到文件、读取文件的功能。
 * 主要区别：
 * 1. 引入了对象序列化和反序列化，将用户信息以对象的形式写入和读取文件。
 * 2. 增加了“保存文件”和“读取文件”按钮，使用户能够将用户信息保存到文件和从文件中加载用户信息。
 * 3. 通过文件保存和读取，实现了数据的持久化。
 * 4. 用户信息存储方式从List改为了Map，使用用户ID作为键，方便根据ID进行快速查找和删除。
 *
 * @author Hsu琛君珩
 * @version 1.0
 */
public class Experiment7_2 extends JFrame {
    private JLabel idLab; // 用户编号标签
    private JLabel nameLab; // 用户姓名标签
    private JTextField idInput; // 用户编号输入框
    private JTextField nameInput; // 用户姓名输入框
    private JButton positiveBtn; // 确认按钮
    private JButton deleteBtn; // 删除按钮
    private JButton showBtn; // 显示按钮
    private JButton saveToFileBtn; // 保存文件按钮
    private JButton loadFromFileBtn; // 读取文件按钮
    private JTextArea info; // 多行文本区域，用于显示用户信息
    private Map<String, User> userList; // 使用 Map 存储用户对象，以用户ID作为键

    public Experiment7_2() {
        // 设置窗口标题
        setTitle("用户信息管理");
        // 设置窗口可见
        setVisible(true);
        // 设置窗口大小，宽度为400像素，高度为300像素
        setSize(400, 300);
        // 使用流式布局管理器
        setLayout(new FlowLayout());
        // 设置窗口关闭操作为退出应用程序
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 创建用户编号标签
        idLab = new JLabel("用户编号");
        // 创建用户姓名标签
        nameLab = new JLabel("用户姓名");
        // 创建用户编号输入框，限制长度为15个字符
        idInput = new JTextField(15);
        // 创建用户姓名输入框，限制长度为15个字符
        nameInput = new JTextField(15);
        // 创建多行文本显示区域，行数为10，列数为30
        info = new JTextArea(10, 30);
        // 设置文本区域自动换行
        info.setLineWrap(true);
        // 创建确认按钮
        positiveBtn = new JButton("确认");
        // 创建删除按钮
        deleteBtn = new JButton("删除");
        // 创建显示按钮
        showBtn = new JButton("显示");
        // 创建保存文件按钮
        saveToFileBtn = new JButton("保存文件");
        // 创建读取文件按钮
        loadFromFileBtn = new JButton("读取文件");
        // 使用 HashMap 存储用户对象
        userList = new HashMap<>();

        // 将组件添加到窗口
        add(idLab);
        add(idInput);
        add(nameLab);
        add(nameInput);
        add(positiveBtn);
        add(deleteBtn);
        add(showBtn);
        add(saveToFileBtn);
        add(loadFromFileBtn);
        add(new JScrollPane(info)); // 使用滚动窗格包装文本区域

        // 添加确认按钮的点击事件监听器
        positiveBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                addUser(); // 调用 addUser() 方法处理确认按钮点击事件
            }
        });

        // 添加删除按钮的点击事件监听器
        deleteBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                deleteUser(); // 调用 deleteUser() 方法处理删除按钮点击事件
            }
        });

        // 添加显示按钮的点击事件监听器
        showBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                showUsers(); // 调用 showUsers() 方法处理显示按钮点击事件
            }
        });

        // 添加保存文件按钮的点击事件监听器
        saveToFileBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                saveToFile(); // 调用 saveToFile() 方法处理保存文件按钮点击事件
            }
        });

        // 添加读取文件按钮的点击事件监听器
        loadFromFileBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                loadFromFile(); // 调用 loadFromFile() 方法处理读取文件按钮点击事件
            }
        });
    }

    /**
     * 添加用户到用户列表
     */
    private void addUser() {
        String name = nameInput.getText();
        String id = idInput.getText();

        if (name.isEmpty() || id.isEmpty()) {
            info.setText("输入不能为空，请重新输入");
        } else if (!isValidUserId(id)) {
            info.setText("格式不对！");
        } else {
            info.setText("欢迎你，" + name + "用户");
            User user = new User(name, id);
            userList.put(id, user);
        }
    }

    /**
     * 从用户列表删除用户
     */
    private void deleteUser() {
        String id = idInput.getText();
        String name = nameInput.getText();

        if (id.isEmpty() || name.isEmpty()) {
            info.setText("用户ID和姓名不能为空，请重新输入");
        } else if (userList.containsKey(id)) {
            User user = userList.get(id);
            if (user.getName().equals(name)) {
                userList.remove(id);
                info.setText("删除成功");
            } else {
                info.setText("用户ID和姓名不匹配");
            }
        } else {
            info.setText("未找到用户ID：" + id);
        }
    }

    /**
     * 显示用户列表信息
     */
    private void showUsers() {
        StringBuilder userInfos = new StringBuilder("用户列表:\n");
        for (User user : userList.values()) {
            userInfos.append(user.toString()).append("\n");
        }
        info.setText(userInfos.toString());
    }

    /**
     * 将用户信息保存到文件
     */
    private void saveToFile() {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user_data.ser"))) {
            oos.writeObject(userList);
            info.setText("用户信息已保存到文件");
        } catch (IOException e) {
            e.printStackTrace();
            info.setText("保存文件失败");
        }
    }

    /**
     * 从文件加载用户信息
     */
    private void loadFromFile() {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user_data.ser"))) {
            userList = (Map<String, User>) ois.readObject();
            info.setText("用户信息已从文件加载");
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            info.setText("加载文件失败");
        }
    }

    /**
     * 校验用户编号格式
     *
     * @param userId 用户编号
     * @return 校验结果
     */
    private boolean isValidUserId(String userId) {
        return userId.startsWith("2019");
    }

    /**
     * 主方法，启动 Swing 应用
     *
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Experiment7_2();
            }
        });
    }
}
